function TextInput(){
    this.init$Eventable();
    this.initRenderable();
    this.$focusElm = null;
    this.$readOnly = false;
    this.$inComposition = false;
}

TextInput.prototype = {
    _TPL_ELM: '<div id="#{id}_wrapper" tabindex="-1" style="position:absolute;left:0;top:0;width:0;height:0;overflow:hidden;">' +
        '<textarea id="#{id}_input" style="width:1px;height:1px;white-space:nowrap;position:absolute;top:20px;"></textarea>' +
        '</div>',
    _wrapperElm: function (){
        return this.elm('wrapper');
    },
    _inputElm: function (){
        return this.elm('input');
    },
    renderHTML: function (containerElm){
        return Utils.format(this._TPL_ELM, { id: this.id() });
    },
    postRender: function (){
        var wrapperElm = this._wrapperElm();
        var inputElm = this._inputElm();
        if ('oninput' in inputElm) {
            this.on(inputElm, 'input', this._onTextInput);
        } else if ('onpropertychange' in inputElm) {
            this.on(inputElm, 'propertychange', this._onPropertyChange);
        }
        if (Utils.isOldIE) {
            this.on(inputElm, 'keyup', this._onTextKeyUp);
        } else {
            this.on(inputElm, 'compositionstart', this._onCompositionStart);
            this.on(inputElm, 'compositionend', this._onCompositionEnd);
        }
        this.on(wrapperElm, 'keydown', this._onKeyDown);
        this.on(wrapperElm, 'keyup', this._onKeyUp);
        this._updateFocusElm();
    },
    inComposition: function (){
        return this.$inComposition;
    },
    _onTextInput: function (evt){
        var self = this;
        setTimeout(function (){
            if (!self.inComposition()) {
                self.sendText();
            }
        });
    },
    _onPropertyChange: function (){
        if (Utils.isOldIE && this._inputElm().value.charAt(0) > 128) return;
        var self = this;
        setTimeout(function (){
            if (!self.inComposition()) {
                self.sendText(null);
            }
        });
    },
    _onCompositionStart: function (){
        this.$inComposition = true;
    },
    _onCompositionEnd: function (){
        this.$inComposition = false;
    },
    _onTextKeyUp: function (evt){
        var self = this;
        if (this.inComposition()) {
            if (!this._inputElm().value || evt.keyCode == 13 || evt.keyCode == 27) {
                setTimeout(function (){
                    self._onCompositionEnd();
                });
            }
        }
        if ((this._inputElm().value.charCodeAt(0)|0) > 128) {
            this._onCompositionStart();
        }
        DOMUtils.preventDefault(evt);
    },
    _onKeyDown: function (evt){
        this.$event = evt;
        this.dispatchEvent({
            type: 'KeyDown',
            ctrlKey: evt.ctrlKey,
            altKey: evt.altKey,
            shiftKey: evt.shiftKey,
            keyCode: evt.keyCode,
            preventDefault: function (){
                DOMUtils.preventDefault(evt);
            }
        });
        this.$event = null;
    },
    _onKeyUp: function (evt){
        this.$event = evt;
        this.dispatchEvent({
            type: 'KeyUp',
            ctrlKey: evt.ctrlKey,
            altKey: evt.altKey,
            shiftKey: evt.shiftKey,
            keyCode: evt.keyCode,
            preventDefault: function (){
                DOMUtils.preventDefault(evt);
            }
        });
        this.$event = null;
    },
    _onFocus: function (evt){
        if (evt.target === this.$focusElm) {
            this.dispatchEvent({ type: 'focus' });
        }
    },
    _onBlur: function (evt){
        if (evt.target === this.$focusElm) {
            this.dispatchEvent({ type: 'blur' });
        }
    },
    _updateFocusElm: function (){
        var alreadyFocused = this.isFocused();
        var oldFocusElm = this.$focusElm;
        this.$focusElm = this.readOnly() ? this._wrapperElm() : this._inputElm();
        if (this.$focusElm !== oldFocusElm) {
            if (oldFocusElm != null) {
                this.un(oldFocusElm, 'focus', this._onFocus);
                this.un(oldFocusElm, 'blur', this._onBlur);
            }
            this.on(this.$focusElm, 'focus', this._onFocus);
            this.on(this.$focusElm, 'blur', this._onBlur);
            if (alreadyFocused) {
                this.focus();
            }
        }
    },
    readOnly: function (){
        return this.$readOnly;
    },
    setReadOnly: function (readOnly){
        this.$readOnly = readOnly;
        this._updateFocusElm();
    },
    setPosition: function (pos){
        this._wrapperElm().style.left = pos[0] + 'px';
        this._wrapperElm().style.top = pos[1] + 'px';
    },
    focus: function (){
        var self = this;
        self.$focusElm.focus();
        setTimeout(function (){
            self.$focusElm.focus();
        });
    },
    isFocused: function (){
        return this.$focusElm && this.$focusElm.ownerDocument.activeElement === this.$focusElm;
    },
    blur: function (){
        if (this.isFocused()) {
            this.$focusElm.blur();
        }
    },
    setText: function (text){
        this._inputElm().value = text;
        this._inputElm().select();
    },
//    getText: function (){
//        return this._inputElm().value;
//    },
    sendText: function (text){
        var inputElm = this._inputElm();
        if (text == null) {
            text = inputElm.value;
            if (text.charCodeAt(text.length - 1) == 0) {
                text = text.slice(0, -1);
            }
        }
        if (text && !this.readOnly()) {
            this.dispatchEvent({ type: 'TextInput', text: text });
        }
        inputElm.value = '\0';
        try {
            inputElm.select();
        } catch(ex){}
    }
};

Utils.extend(TextInput, Eventable);
Utils.extend(TextInput, Renderable);
